package com.example.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.common.utils.ApiResult;
import com.example.common.utils.DateFormatUtil;
import com.example.common.utils.RadarUtil;
import com.example.model.entity.SuppliesType;
import com.example.service.SuppliesRealinfoService;
import com.example.service.SuppliesService;
import com.example.service.impl.SuppliesTypeServiceImpl;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;
import static com.example.config.SocketHandler.*;

/**
 * @author zhangr
 * 自定义封装的连接的客户端
 */
@Slf4j
@Data
@Configuration
public class ClientSocket implements Runnable{

    private Socket socket;
    private DataInputStream inputStream;
    private DataOutputStream outputStream;
    private String key;
    private String message;
    private static ClientSocket  clientSocket ;
    @Autowired
    private SuppliesRealinfoService suppliesRealinfoService;//测试使用

    @Autowired
    private SuppliesService suppliesService;

    @Autowired
    private SuppliesTypeServiceImpl suppliesTypeServiceImpl;

    @PostConstruct //通过@PostConstruct实现初始化bean之前进行的操作
    public void init() {
        clientSocket = this;
        clientSocket.suppliesRealinfoService = this.suppliesRealinfoService;
        clientSocket.suppliesService = this.suppliesService;
        clientSocket.suppliesTypeServiceImpl = this.suppliesTypeServiceImpl;
        // 初使化时将已静态化的testService实例化
    }
    //开启一个队列用于存放TCP数据
    List<Byte> queueFinal = new LinkedList<Byte>();
    //定义包头包尾
    byte[] head = {10, 10};
    int headIndex = -1;

    @Override
    public void run() {
        while (true) {
//            try {
//                TimeUnit.SECONDS.sleep(10);
//
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            if (isSocketClosed(this)){
//                log.info("客户端已关闭,其Key值为：{}", this.getKey());
//                //关闭对应的服务端资源
//                close(this);
//                break;
//            }
            try {
                InputStream inputStream = socket.getInputStream();
                DataInputStream dataInputStream =new DataInputStream(inputStream);
                int len = 0;
                while (len == 0) {
                    len = dataInputStream.available();
                    if(len == 0){
                        Thread.sleep(10);
                    }
                }
                byte[] bytes = new byte[len];
                dataInputStream.read(bytes);
                log.info(new String(bytes,"GBK"));
                //将数据全部存入临时缓冲区
                for (byte b : bytes) {
                    queueFinal.add(b);
                }
                //处理断包、粘包
                while (true) {
                    headIndex = RadarUtil.indexOfArray(queueFinal, head);
//                    headIndex = 0;
                    if (headIndex >= 0){
                        //提取长度
                        int numLeft = bytes[headIndex+2];
                        int numRight = bytes[headIndex+3];
                        int numLength = 0;
                        log.info("高位长度="+numLeft+",低位长度="+numRight);
                        if(numRight>0){
                            numLength = numLeft*256 + numRight;
                        }else{
                            String StringRight = Integer.toHexString(numRight& 0XFF);
                            BigInteger bigint=new BigInteger(StringRight, 16);
                            numRight = bigint.intValue();
                            numLength = numLeft*256 + numRight;
                        }
                        log.info("计算后长度为="+numLength);
                        log.info("包长度为="+queueFinal.size());
                        if(numLength <= queueFinal.size()){
                            byte[] bytesFinal = new byte[numLength];
                            //丢弃临时缓冲区里 起始头 前面的数据
                            for (int i = 0; i < headIndex; i++) {
                                queueFinal.remove(0);
                            }
                            for (int i = 0; i < bytesFinal.length; i++) {
                                bytesFinal[i] = queueFinal.get(0);
                                queueFinal.remove(0);
                            }
                            if(bytesFinal[0] != 10 || bytesFinal[1] != 10){
                                log.info("起始头不正确");
                                queueFinal.clear();
                                break;
                            }
                            //分离起始头，包长，类型-----包体
                            byte[] botyBytes = new byte[numLength-6];
                            //被分割数组，开始分割下标，分割生成目标，生成目标开始下标，生成长度
                            System.arraycopy(bytesFinal,6,botyBytes,0,numLength-6);
                            int typeLeft = bytesFinal[4] * 256;
                            int typeRight = bytesFinal[5];
                            int type = typeLeft + typeRight;
                            log.info("上报事件类型为===="+type);
                            String jsonStr = new String(botyBytes,"GBK");
                            log.info("截取后的Str="+jsonStr);
                            if(type == 1){
                                //上报事件
                                log.info("心跳");
                                JSONObject json = JSONObject.parseObject(jsonStr);
                                String dev_id = json.getString("dev_id");
                                if(dev_id == null){
                                    log.info("dev_id不存在");
                                    break;
                                }
                                //阈值
                                String threshold =  clientSocket.suppliesTypeServiceImpl.getInfoBySuppliesId(dev_id);
                                if(threshold != ""){
                                    JSONObject typeJson = JSON.parseObject(threshold);
                                    typeJson.put("dev_id", dev_id);
                                    typeJson.put("date_time", DateFormatUtil.getNowDateTimeString());
                                    byte[] returnHeader = new byte[6];
                                    returnHeader[0] = 10;
                                    returnHeader[1] = 10;
                                    byte[] bytesa = threshold.getBytes("GBK");
                                    int length = bytesa.length + 6;
                                    if(length > 256){
                                        returnHeader[2] = (byte) (length / 256);
                                        returnHeader[3] = (byte) (length % 256);
                                    }else{
                                        returnHeader[2] = 0;
                                        returnHeader[3] = (byte) length;
                                    }
                                    returnHeader[4] = 0;
                                    returnHeader[5] = 2;
                                    sendMessageAndThreshold(this,threshold,returnHeader,length);
                                }else{
                                    bytesFinal[4] = 0;
                                    bytesFinal[5] = 2;
                                    sendMessage(this,bytesFinal);
                                }
                                log.info("回复心跳成功");
//                                queueFinal.clear();
                            }else if (type == 3 || type == 4|| type == 5){
                                //解析数据并存入数据库
                                log.info("数据类型为"+type+",开始存入数据库");
                                ApiResult<Boolean> apiResult =  clientSocket.suppliesRealinfoService.saveRealinfo(jsonStr);
                                if(apiResult.getData() == Boolean.FALSE){
                                    queueFinal.clear();
                                    break;
                                }
                            }
                            //粘包，即包尾后还有内容，如果没有粘包则继续发送tcp请求收取下一帧数据
                            if (queueFinal.size() > 0) {
                                log.info("粘包了");
                            }else {
                                break;
                            }
                        }else {
                            //断包，即接收到的包不完整，则跳出内圈循环，进入外圈循环，从输入流中继续读取数据
                            log.info("断包了");
                            break;
                        }
                    }else if ( headIndex == -1 ) {
                        //包头都没有，直接丢弃数据
                        log.info("包头验证不通过");
//                        Thread.sleep(10);
                        queueFinal.clear();
                        break;
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}